#include "FreeRTOS.h"
#include "task.h"
#include "qelib.h"
#include "xil_assert.h"
#include "xil_exception.h"
#include "project_config.h"



QELOG_DOMAIN("main");



/* freertos application assert hook */
//void vApplicationAssert(const char *file, uint32_t line)
//{
//    qe_fatal("application assert %s:%d", file, line);
//    qe_ringbuffer *rb = qelog_get_buffer();
//    qe_ringbuffer_wait(rb);
//    while(1);
//}
//
///* freertos stack overflow hook */
//void vApplicationStackOverflowHook(TaskHandle_t task, char *name)
//{
//    qe_fatal("stack overflow %s", name);
//    while(1);
//}

/* freertos message hook */
void vApplicationAssertMsg(const char *file, qe_u32 line, const char *msg)
{
    qe_fatal("application assert %s %s:%d", msg, file, line);
    while(1);
}

/* hylib assert hook */
static void assert_hook(const char *ex_string, const char *func, qe_size line)
{
    qe_fatal("assert %s %s:%d", ex_string, func, line);
    while(1);
}

static void xil_assert_hook(const char8 *File, s32 Line)
{
    qe_fatal("xil assert %s:%d", File, Line);
    while(1);
}

static void exception_prefertch_abort(void *args)
{
    qe_fatal("prefertch abort exception");
    while(1);
}

//static void exception_data_abort(void *args)
//{
//    qe_fatal("data abort exception");
//    while(1);
//}
//
//static void exception_undefined(void *args)
//{
//    qe_fatal("undefined exception");
//    while(1);
//}

static char heap_pool[HEAP_SIZE];

static void mem_init(void)
{
    qemem_set_pool(heap_pool, sizeof(heap_pool));
}

static void log_init(void)
{
    qe_u32 flags = 0x0;

    /*
     * Make sure that if you not use 'HYLOG_RECUR', interrupt context
     * can't use log, because 'HYLOG_RECUR' will use static buffer in
     * logging handler, if 'HYLOG_RECUR' not set, buffer is dynamic
     * alloced by freertos allocator, pvPortMalloc will make critical
     * nest.
     */
    flags = QELOG_DM |
            QELOG_LV |
            QELOG_CL |
            QELOG_HMS|
            QELOG_RECUR|
            QELOG_RB|
            QELOG_PTS;

    qelog_init(LOG_LEVEL, flags);

#if (LOG_BUFSZ)
    char *buffer;
    buffer = qe_malloc(LOG_BUFSZ);
    qelog_set_buffer(buffer, LOG_BUFSZ);
#endif
}

static void assert_init()
{
    /* Set hylib assert hook */
    qe_assert_set_hook(assert_hook);

    /* Set xilinx assert */
    Xil_AssertSetCallback(xil_assert_hook);
}

static void exception_init()
{
    Xil_ExceptionInit();
    Xil_ExceptionEnable();

    Xil_ExceptionRegisterHandler(
    	XIL_EXCEPTION_ID_SERROR_ABORT_INT,
        exception_prefertch_abort, QE_NULL);
}

int main(void)
{
    /* Memory init */
    mem_init();

    /* Log init */
    log_init();

    assert_init();

    exception_init();

    /* Initcall */
    qe_initcall();

    /* Start freertos scheduler */
    vTaskStartScheduler();

    qe_assert(0);

    return 0;
}
